#include <stdio.h>
#include <time.h>
#include <windows.h>

void menu() // 输出菜单
{
	printf("\t*************************************************\n");
	printf("\t**      模拟洗牌发牌(52张扑克牌)小程序         **\n");
	printf("\t**   将4种花色,每种A-K共13张牌,洗牌后发4叠牌   **\n");
	printf("\t**     洗过的牌组会自动存储到文件date.txt中    **\n");
	printf("\t*************************************************\n");
}

typedef struct // 定义扑克牌结构体
{
	char number[10];
	char color;
} Card; // 类型名重定义为Card

void FillDeck(Card *wDeck, char *wNumber[], int wColor[]) // 初始化扑克牌
{
	int i = 0;
	int j = 0;
	for (j = 0; j < 4; j++) // 4叠扑克牌
	{
		for (i = j * 13; i < (j + 1) * 13; i++) // 每叠13张
		{
			strcpy(wDeck[i].number, wNumber[i % 13]);
			wDeck[i].color = wColor[j];
		}
	}
}

void Shuffle(Card *wDeck) // 洗牌
{
	int i = 0;
	int j = 0;
	for (i = 0; i < 52; i++)
	{
		j = rand() % 52; // 随机数0-51,对应52张牌
		Card temp = wDeck[i];
		wDeck[i] = wDeck[j];
		wDeck[j] = temp;
	}
}

void Deal(Card *wDeck) // 发牌(显示扑克牌)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < 4; i++)
	{
		printf("%d:\n", i + 1);
		printf(" --  --  --  --  --  --  --  --  --  --  --  --  --\n"); // 模拟牌的样式
		for (j = i * 13; j < (i + 1) * 13; j++)
		{
			printf("|%c |", wDeck[j].color);
		}
		printf("\n");
		for (j = i * 13; j < (i + 1) * 13; j++)
		{
			if (strcmp(wDeck[j].number, "10") != 0)
				printf("| %s|", wDeck[j].number);
			else // 扑克牌号码为10时，"10"占了两个空间,为了排版整齐,前面去掉空格
				printf("|%s|", wDeck[j].number);
		}
		printf("\n");
		printf(" --  --  --  --  --  --  --  --  --  --  --  --  --\n");
	}
}

int Write_File(Card *wDeck) // 存储发牌到文件
{
	FILE *fp = fopen("date.dat", "w"); // 只写
	if (fp == NULL)
	{
		perror("fopen");
		return -1; // 遇到错误时函数结束
	}
	fwrite(wDeck, sizeof(Card), 52, fp); // 写入文件
	fclose(fp);
	fp = NULL;
}

int Read_File() // 从文件中读牌
{
	FILE *fp = fopen("date.dat", "r"); // 只读
	if (fp == NULL)
	{
		perror("fopen");
		return -1; // 遇到错误时函数结束
	}
	Card nDeck[52]; // 重新定义一个card结构体
	Card *pointer = nDeck;
	fread(pointer, sizeof(Card), 52, fp); // 把文件中洗牌情况读取到nDeck中
	fclose(fp);
	fp = NULL;
	int Input = -1;
l1:
	while (1)
	{
		printf("你想查看哪一叠扑克牌?(1 / 2 / 3 / 4,输入0退出)\n"); // 让观众选择模式
		scanf("%d", &Input);
		if (!Input)
			break;
		else if (Input != 1 && Input != 2 && Input != 3 && Input != 4)
		{
			printf("输入错误,请重新输入!\n");
			goto l1;
		}
		int i = 0;
		switch (Input) // 根据选择看哪一叠,初始化指针位置
		{
		case 1:
			pointer = nDeck;
			break;
		case 2:
			pointer = nDeck + 13;
			break;
		case 3:
			pointer = nDeck + 26;
			break;
		case 4:
			pointer = nDeck + 39;
			break;
		default:
			break;
		}
		printf("第%d叠:\n", Input);
		printf(" --  --  --  --  --  --  --  --  --  --  --  --  --\n"); // 模拟牌的样式
		while (i < 13)
		{
			printf("|%c |", (*pointer).color);
			i++;
			pointer++;
		}
		printf("\n");
		i = 0;
		pointer -= 13; // 初始化i和pointer
		while (i < 13)
		{
			if (strcmp((*pointer).number, "10") != 0)
				printf("| %s|", (*pointer).number);
			else // 扑克牌号码为10时，"10"占了两个空间,为了排版整齐,前面去掉空格
				printf("|%s|", (*pointer).number);
			i++;
			pointer++;
		}
		printf("\n --  --  --  --  --  --  --  --  --  --  --  --  --\n");
	}
}

void game() // 游戏主体
{
	Card wDeck[52];
	char *wNumber[13] = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}; // 定义牌上13种数字
	int wColor[4] = {3, 4, 5, 6};															// 定义牌上四种花色,用%c格式化输出即可
	FillDeck(wDeck, wNumber, wColor);														// 初始化
	printf("这里有一副新扑克牌:\n");
	Deal(wDeck); // 输出扑克牌原状
	printf("按下任意键开始洗牌\n");
	system("pause");
	printf("正在洗牌. . .\n");
	Shuffle(wDeck); // 洗牌
	Sleep(3000);	// 暂停三秒模拟洗牌
	printf("洗牌结束\n");
	/*去掉下一行注释后, 可直接分别输出洗牌后4叠牌结果*/
	// Deal(wDeck);
	Write_File(wDeck); // 存储洗牌情况到文件
	Read_File();	   // 从文件中读取牌组并输出
}

int main() // 主函数
{
	srand((int)time(NULL)); // 随机数种子
	menu();					// 输出菜单
	game();					// 游戏本体
	return 0;
}
